#include "StdAfx.h"
#include "Atom.h"

using namespace m4aSharp;

Atom::Atom(String^ name)
{
	Debug::Assert(String::IsNullOrEmpty(name) == false);

	_name = name;
	_atoms = gcnew List<Atom^>();
}

Object^ Atom::InterpretData()
{
	if (Data != nullptr)
	{
		try
		{
			if (Parent != nullptr)
			{
				if (Parent->Name == "trkn" || Parent->Name == "disk")
					return UInt16FromBigEndian(6);

				if (Parent->Name == "gnre")
					return UInt16FromBigEndian(4);

				if (Parent->Name == "cpil")
					return Data[4] == 1;

				if (Parent->Name == "rtng")
					return Data[4];

				if (Parent->Name == "covr")
					return ExtractImage();
			}

			if (Name != "clyr" && Data->Length > 255)	// lyrics can be greater than 255 and a string
				return "object";						// everything else that size is theoretically a packed object

			if (Name == "mvhd" || Name == "tkhd" || Name == "mdhd" || Name == "esds")
				return "object";

			return Encoding::UTF8->GetString(Data)->Trim('\0');
		}
		catch(Exception^ e)
		{
			Debug::WriteLine("ERROR:" + e->Message);
		}
	}
				
	return nullptr;		
}

void Atom::SetData(array<Byte>^ data)
{
	_data = data;
}

void Atom::AddChildAtom(Atom^ child)
{
	Debug::Assert(child != nullptr);

	_atoms->Add(child);
	child->SetParent(this);
}

Image^ Atom::ExtractImage()
{
	if (Data != nullptr && Data->Length > 4)
	{
		MemoryStream^ stream = gcnew MemoryStream(Data, 4, Data->Length - 4);
		try
		{		
			return Image::FromStream(stream, true, true);
		}
		finally
		{
			stream->Close();
		}
	}

	return nullptr;
}

void Atom::SetParent(Atom^ atom)
{
	_parent = atom;
}

UInt16 Atom::UInt16FromBigEndian(int offset) 
{
	Debug::Assert(_data != nullptr);
	return ((_data[offset] & 0xff) << 8 | _data[offset + 1] & 0xff) << 0;
}
		
String^ Atom::ToString()
{
	return Name;
}

